﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;

public class UtilsMath
{
    public static bool IsInsideTrangle(Vector3 p, Vector3 p0, Vector3 p1, Vector3 p2 )
    {
        var line0 =  p0- p;
        var line1 =  p1- p;
        var line2 =  p2- p;

        var angle0d = Vector3.Cross(line0, line1).z;
        var angle1d = Vector3.Cross(line1, line2).z;
        var angle2d = Vector3.Cross(line2, line0).z;

        if ((angle0d > 0 && angle1d > 0 && angle2d > 0 ) ||
            (angle0d < 0 && angle1d < 0 && angle2d < 0))
        {
            return true;
        }
        return false;
    } 
    public static bool IsRectangleInside2D(Vector2 p, Vector2 p0, Vector2 p1, Vector2 p2, Vector2 p3)
    {
        if (Vector2.Dot((p1 - p0), (p - p0)) >= 0 &&
            Vector2.Dot((p3 - p0), (p - p0)) >= 0 &&
            Vector2.Dot((p3 - p2), (p - p2)) >= 0 &&
            Vector2.Dot((p1 - p2), (p - p2)) >= 0)
        {
            return true;
        }
        return false;
    }
    public static Vector3 Bezier2(Vector3 p0, Vector3 p1, Vector3 contorlP, float t)
    {
        return (p0 * Mathf.Pow(1 - t, 2)) + contorlP * ((2.0f * t) * (1.0f - t)) + p1 * Mathf.Pow(t, 2);
    }

    public static bool IsInsidePolygon2D(Vector3 p, List<Vector3> points)
    {
        var indexes = CalcPolygon(points);

        for (int i = 2; i < indexes.Count; ++i)
        {
            Vector3 p0 = points[indexes[i - 2]];
            Vector3 p1 = points[indexes[i - 1]];
            Vector3 p2 = points[indexes[i]];

            if (IsInsideTrangle(p, p0, p1, p2))
            {
                return true;
            }
        }
        return false;
    }

	public static List<int> CalcPolygon(List<Vector3> points)
	{
		//顺时针排序(先找到一个凸点p，然后得到(p-1,p) , (p, p+1)两个向量进行叉乘得到多边形绕序)
		SortPoints(points);

		//	构建三角面
		List<int> indexes = new List<int>();
		List<KeyValuePair<int, Vector3>> vetricesMap = new List<KeyValuePair<int, Vector3>>();
		for (int i = 0; i < points.Count; ++i)
		{
			vetricesMap.Add(new KeyValuePair<int, Vector3>(i, points[i]));
		}
		bool isActivity = true;
		while (isActivity)
		{
			isActivity = false;
			for (int i = 0; i < (vetricesMap.Count - 2); ++i)
			{
				Vector3 p0 = vetricesMap[i + 0].Value;
				Vector3 p1 = vetricesMap[i + 1].Value;
				Vector3 p2 = vetricesMap[i + 2].Value;

				Vector3 A = p1 - p0;
				Vector3 B = p2 - p1;
				Vector3 result = Vector3.Cross(A, B);

				//	如果三角面中有其他的点，则不处理
				bool isHaveTriangular = false;
				for (int j = 0; j < points.Count; ++j)
				{
					if (j == vetricesMap[i + 0].Key ||
						j == vetricesMap[i + 1].Key ||
						j == vetricesMap[i + 2].Key)
					{
						continue;
					}
					isHaveTriangular = IsInsideTrangle(points[j], p0, p1, p2);
					if (isHaveTriangular)
					{
						break;
					}
				}
				if (result.z <= 0 && !isHaveTriangular)
				{
					indexes.Add(vetricesMap[i + 2].Key);
					indexes.Add(vetricesMap[i + 1].Key);
					indexes.Add(vetricesMap[i + 0].Key);
					vetricesMap.Remove(vetricesMap[i+1]);
					isActivity = true;
				}
			}
		}
		return indexes;
	}

	public static bool SortPoints(List<Vector3> points)
	{
		bool isSort = false;
		//顺时针排序(先找到一个凸点p，然后得到(p-1,p) , (p, p+1)两个向量进行叉乘得到多边形绕序)
		if (points.Count >= 3)
		{
			int p = 0;
			for (int i = 0; i < points.Count; ++i)
			{
				Vector3 posMax = points[p];
				Vector3 pos = points[i];
				if (pos.x != 0 && pos.y != 0 && pos.x > posMax.x)
				{
					p = i;
				}
			}

			int ps1 = p == 0 ? (points.Count - 1) : (p - 1);
			int pp1 = p == (points.Count - 1) ? 0 : (p + 1);

			Vector3 pPos = points[p];
			Vector3 ps1Pos = points[ps1];
			Vector3 pp1Pos = points[pp1];

			ps1Pos = ps1Pos - pPos;
			pp1Pos = pPos - pp1Pos;

			Vector3 crossResult = Vector3.Cross(ps1Pos, pp1Pos);
			if (crossResult.z > 0)
			{
				List<Vector3> copy = points;
				for (int i = 0; i < copy.Count; ++i)
				{
					points[i] = copy[copy.Count - i - 1];
				}
				isSort = true;
			}
		}
		return isSort;
	}
}